package com.promfy.navm.views;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.promfy.nvam.util.L;

public class CusDrawView extends View {
	private static final String TAG = "navi";

	protected static final int MSG_WHAT_INVAIDATE = 0;

	/**
	 * touch state
	 * 
	 * @author promfy
	 * 
	 */
	enum State {
		FLOATING, TOUCH_DOWN, TOUCH_MOVING, LONG_PRESSED
	}

	enum TouchSection{
		NULL,TOP_LEFT,TOP_RIGHT,BOTTOM_LEFT,BOTTOM_RIGHT
	}
	
	private State state = State.FLOATING;

	/**
	 * constant var
	 */
	public static int CENTER_LENGTH = 200;
	public static int INNER_RIDUS_LENGTH = 80;
	public static int INNER_RIDUS_STROKE = 10;
	public static int DEGREE_PADDING = 3;

	/**
	 * draw
	 */
	private Paint p;
	private Path path = new Path();
//	private Path path2 = new Path();
//	private Path path3 = new Path();
//	private Path path4 = new Path();

	/**
	 * timer
	 */
	Timer timer;
	
	private Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			switch(msg.what){
			case MSG_WHAT_INVAIDATE:
				invalidate();
				break;
			}
		};
	};

	private TouchSection touchSection = TouchSection.NULL;

	public CusDrawView(Context context) {
		super(context);
	}
	
	

	public CusDrawView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public CusDrawView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}



	RectF oval1 = new RectF(0, 0, CENTER_LENGTH * 2, CENTER_LENGTH * 2);
	RectF oval = new RectF(//
			CENTER_LENGTH - INNER_RIDUS_LENGTH, //
			CENTER_LENGTH - INNER_RIDUS_LENGTH, //
			CENTER_LENGTH + INNER_RIDUS_LENGTH, //
			CENTER_LENGTH + INNER_RIDUS_LENGTH);
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		p = new Paint();
		p.setColor(Color.BLUE);
		p.setAlpha(100);
		p.setAntiAlias(true);
		canvas.drawCircle(CENTER_LENGTH, CENTER_LENGTH,
				INNER_RIDUS_LENGTH - INNER_RIDUS_STROKE, p);

		// p.setStyle(Paint.Style.STROKE);
		// p.setStrokeWidth(2);
		L.v(TAG, "onDraw() state: " + state);

		switch (state) {
		case FLOATING:
			break;
		case LONG_PRESSED:
			canvas.drawCircle(CENTER_LENGTH, CENTER_LENGTH, CENTER_LENGTH - 10,
					p);
			break;
		case TOUCH_DOWN:
			drawCanvas(canvas);
			
			break;
		case TOUCH_MOVING:
			drawCanvas(canvas);
			drawCanvasPressed(canvas);
			break;
		}

	}

	private void drawCanvasPressed(Canvas canvas) {
		p.setColor(Color.RED);
		switch (touchSection) {
		case TOP_LEFT:
			path.reset();
			path.arcTo(oval1, -180 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
			path.arcTo(oval, -90 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
			path.close();
			canvas.drawPath(path, p);
			break;
		case TOP_RIGHT:
			path.reset();
			path.arcTo(oval1, -90 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
			path.arcTo(oval, 0 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
			path.close();
			canvas.drawPath(path, p);
			
			break;
		case BOTTOM_LEFT:
			
			// BOTTOM_LEFT
			path.reset();
			path.arcTo(oval1, 90 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
			path.arcTo(oval, -180 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
			path.close();
			canvas.drawPath(path, p);
			break;
		case BOTTOM_RIGHT:
			// BOTTOM_RIGHT
			path.reset();
			path.arcTo(oval1, 0 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
			path.arcTo(oval, 90 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
			path.close();
			canvas.drawPath(path, p);
			
			break;
			
		default:
			break;
		}
	}

	private void drawCanvas(Canvas canvas) {
		// TOP_LEFT
		path.reset();
		path.arcTo(oval1, -180 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
		path.arcTo(oval, -90 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
		path.close();
		canvas.drawPath(path, p);

		// TOP_RIGHT
		path.reset();
		path.arcTo(oval1, -90 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
		path.arcTo(oval, 0 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
		path.close();
		canvas.drawPath(path, p);

		// BOTTOM_RIGHT
		path.reset();
		path.arcTo(oval1, 0 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
		path.arcTo(oval, 90 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
		path.close();
		canvas.drawPath(path, p);

		// BOTTOM_LEFT
		path.reset();
		path.arcTo(oval1, 90 + DEGREE_PADDING, 90 - DEGREE_PADDING * 2);
		path.arcTo(oval, -180 - DEGREE_PADDING, -90 + DEGREE_PADDING * 2);
		path.close();
		canvas.drawPath(path, p);
	}
	
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		final MotionEvent e = event;
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if(!isInInnerSection(event)) {
				return false;
			}
			setState(State.TOUCH_DOWN);
			if (timer != null)
				timer.cancel();
			timer = new Timer();
			timer.schedule(new TimerTask() {

				@Override
				public void run() {
					if (state == State.TOUCH_MOVING && isInInnerSection(e)) {
						setState(State.LONG_PRESSED);
						handler.sendEmptyMessage(MSG_WHAT_INVAIDATE);
					}
				}
			}, 1000 * 2);

			invalidate();
			break;
		case MotionEvent.ACTION_MOVE:
			if(state == State.LONG_PRESSED){
				return false;
			}else if(state == State.TOUCH_DOWN){
				setState(State.TOUCH_MOVING);
				computeSectionFlashUI(event);
			}
			break;
		case MotionEvent.ACTION_UP:
			if(state == State.TOUCH_MOVING){
				computeSection(event);
			}else if (state == State.FLOATING){
				return false;
			}
			if (timer != null)
				timer.cancel();
			setState(State.FLOATING);
			invalidate();
			break;
		}
		return true;
	}

	private void setState(State state) {
		L.v(TAG, "setState: " + state);
		this.state = state;
	}
	private void setTouchSection(TouchSection touchSection) {
		L.v(TAG, "setTouchSection: " + touchSection);
		this.touchSection = touchSection;
	}

	/**
	 * compute which section you touched, and execute comman in this section.
	 * @param event
	 */
	private void computeSectionFlashUI(MotionEvent event){
		if(!isInTouchSection(event)) return;
		computeWhichSection(event, false);
	}
	/**
	 * compute which section you touched, and execute comman in this section.
	 * @param event
	 */
	private void computeSection(MotionEvent event){
		if(!isInTouchSection(event)) return;
		computeWhichSection(event,true);
	}
	
	/**
	 * compute if you touched section which is effective.
	 * @param event
	 * @return
	 */
	private boolean isInTouchSection(MotionEvent event){
		float x = event.getX();
		float y = event.getY();
		
		double radius = Math.sqrt((y - CENTER_LENGTH) * (y - CENTER_LENGTH) + (x - CENTER_LENGTH) * (x - CENTER_LENGTH));
		if(radius < CENTER_LENGTH && radius > INNER_RIDUS_LENGTH) {
			L.v(TAG, "isInTouchSection() true");
			return true;
		}
		L.v(TAG, "isInTouchSection() false");
		return false;
	}
	/**
	 * compute if you touched section which is effective.
	 * @param event
	 * @return
	 */
	private boolean isInInnerSection(MotionEvent event){
		float x = event.getX();
		float y = event.getY();
		
		double radius = Math.sqrt((y - CENTER_LENGTH) * (y - CENTER_LENGTH) + (x - CENTER_LENGTH) * (x - CENTER_LENGTH));
		if(radius <  INNER_RIDUS_LENGTH && radius > 0) {
			L.v(TAG, "isInInnerSection() true");
			return true;
		}
		L.v(TAG, "isInInnerSection() false");
		return false;
	}
	
	/**
	 * 
	 * @param event
	 */
	private void computeWhichSection(MotionEvent event,boolean execute){
		float x = event.getX();
		float y = event.getY();
//		double tan = Math.atan(((CENTER_LENGTH-y) / (x -CENTER_LENGTH)));
//		double degree = tan * 180 / Math.PI; 
//		L.d(TAG, "computeWhichSection() before format degree: " + degree);
//		degree = (degree + 360) % 360;
//		L.d(TAG, "computeWhichSection() after format degree: " + degree);
//		
//		if(degree >= 0 && degree < 90){
//			executeTopRight(execute);
//		}
//		else if(degree >= 90 && degree < 180){
//			executeTopLeft(execute);
//		}
//		else if(degree >= 180 && degree < 270){
//			executeBottomLeft(execute);
//		}
//		else if(degree >= 270 && degree < 360){
//			executeBottomRight(execute);
//		}
		
		if(x > CENTER_LENGTH && y < CENTER_LENGTH){
			executeTopRight(execute);
		}
		else if(x < CENTER_LENGTH && y < CENTER_LENGTH){
			executeTopLeft(execute);
		}
		else if(x < CENTER_LENGTH && y > CENTER_LENGTH){
			executeBottomLeft(execute);
		}
		else if(x > CENTER_LENGTH && y > CENTER_LENGTH){
			executeBottomRight(execute);
		}
		invalidate();
	}


	/**
	 * recent 
	 * @param execute 
	 */
	private void executeTopLeft(boolean execute) {
		// TODO Auto-generated method stub
		L.v(TAG, "executeTopLeft()");
		setTouchSection(TouchSection.TOP_LEFT);
		if(execute){
			L.d(TAG, "executeTopLeft() excuted");
			
		}
	}
	
	/**
	 * menu
	 * @param execute 
	 */
	private void executeTopRight(boolean execute) {
		// TODO Auto-generated method stub
		L.d(TAG, "executeTopRight()");
		setTouchSection(TouchSection.TOP_RIGHT);
		if(execute){
			L.d(TAG, "executeTopRight() excuted");
			
		}
	}

	/**
	 * back
	 * @param execute 
	 */
	private void executeBottomLeft(boolean execute) {
		// TODO Auto-generated method stub
		L.d(TAG, "executeBottomLeft()");
		setTouchSection(TouchSection.BOTTOM_LEFT);
		if(execute){
			L.d(TAG, "executeBottomLeft() excuted");
			
		}
	}
	
	/**
	 * home
	 * @param execute 
	 */
	private void executeBottomRight(boolean execute) {
		// TODO Auto-generated method stub
		L.d(TAG, "executeBottomRight()");
		setTouchSection(TouchSection.BOTTOM_RIGHT);
		if(execute){
			L.d(TAG, "executeBottomRight() excuted");
			
		}
	}
}
